<?php

/**
 * Moov API - A suitable platform for file transfer
 *
 * @author      Tobi Martins <tobimartins@gmail.com>
 * @copyright   2014 GEEK INC.
 * @link        http://www.moov.com
 * @license     http://www.moov.com/license
 * @version     1.0.0
 * @package     Moov API
 *
 * MIT LICENSE
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * @author   Tobi Martins
 * @since    1.0.0
 * Import/Include all neccessesary files
 */

require 'utils/Slim/Slim/Slim.php';

//include other necessary files
require_once 'config.php';
require_once 'helper.php';
require_once 'core/database.php';



/*
 * Define constants
 */
define('__MOOV_PARAM_INVAL_', 2);
define('__MOOV_API_ERROR_', 3);


/* 
 * @author   Tobi Martins
 * @since    1.0.0
 * Register Slim
 */
\Slim\Slim::registerAutoloader();

/*
 * @author   Tobi Martins
 * @since    1.0.0
 * Instantiate slim within the moov API
 */
$app = new \Slim\Slim();



/*
 * @author   Tobi Martins
 * @since    1.0.0
 * Routes request without /api to a webpage 
 */

$app->get('/', function () use($app) {
       $template = <<<EOT
               <html>
                 <head>
                   <title> Moov - A Better Way To Send Files </title>
                 </head>
                 <body>
                  <center> Moov - A Better Way To Send Files </center>
                  <center> Website under construction </center> 
                 </body>
               </html>
EOT;
               echo $template;
              
    }
);


/*
 * @author   Tobi Martins
 * @since    1.0.0
 * Routes every API request to this function
 */
$app->group('/api', function () use ($app){
    
    
    /*
     * @author   Tobi Martins
     * @since    1.0.0
     * Routes every module request appropriately
     */
    $app->group('/:user_id+', function () use ($app){
    
        // GET route
        $app->map('/:module+(/:action+)', function ($user_id,$module,$action = NULL) use ($app) {
              global $db;
              global $context;  
              
              //catch unknown module
              switch ($module) {
                  case 'users':
                  case 'contacts':
                  case 'countries':
                  case 'devices':
                  case 'files':
                  case 'settings':
                      require_once './core/'.$module.'.php';
                      break;
                  default:
                      $app->notFound();
              }
             
              // connect to database
              try {
                  $db = new Database();
              } catch (Exception $ex) {
                  error_log( 'Database Connection Erorr '.$ex->getMessage());   
              }
              //copy params
              $params = $app->request()->params();
              
              //process batch call
              if($params['batch']) $params = $params + json_decode ($params);
            
              //populate context
              $context['user_id'] = $user_id;
              $context['module'] = $module;
              $context['action'] = $action;
              $context['params'] = $params;
              
              $http_method = $app->request()->getMethod();
              $action = $action ? $action : ($http_method == 'GET' ? 'list': (($http_method == 'POST' || $http_method == 'DELETE')? 'save':''));
              $func =  "{$module}_{$action}";
              
              //re-route delete request (set status to D) 
              if($http_method == 'DELETE') $params['status'] = 'D';
              
              //extract other non module params before processing request
              $fmt = X_param($params,'fmt');
              
              //the function call takes place here
              $out = $func($params);
              
              /*
               * Handle api errors
               *  
               * 
               * NOTE: Error Parsing and handling needs more creativity
               */
              switch($out) {
                  case __MOOV_PARAM_INVAL_: $app->error(function() use($app,$func){ 
                                            //Invoke error handler
                                            $app->response()->status(400);
                                            $app->response()->body('__MOOV_PARAM_INVAL_: invalid parameter passes to functon '.$func);
                                            $app->stop();
                                            });
                                            $app->error();
                                            
                  case __MOOV_FUNC_CONFUSE_: $app->error(function() use($app,$func){ 
                                            //Invoke error handler
                                            $app->response()->status(400);
                                            $app->response()->body('__MOOV_FUNC_CONFUSE_:  '.$func);
                                            $app->stop();
                                            });
                                            $app->error();
                  case __MOOV_API_ERROR_:   $app->error(function() use($app,$func){ 
                                            //Invoke error handler
                                            $app->response()->status(400);
                                            $app->response()->body('__MOOV_API_ERROR_:  '.$func);
                                            $app->stop();
                                            });
                                            $app->error();
              }
              
              switch ($fmt) {
                  case 'native' :
                      if($out) print_r($out);
                      break;
                  case 'html' :
                      if($out){
                      $table = '<table border=1 cellpadding=5>';
                      //HTML header hack (This Is A Poor Implementation)//
                      foreach ($out as $value) {
                          $table = $table . '<tr>';
                          foreach (array_keys($value) as $val) $table = $table . '<th>' . $val . '</th>';
                          $table = $table . '</tr>';
                          break;
                      }
                      //--------------------------------------------------//
                      foreach ($out as $value) {
                          $table = $table . '<tr >';
                          foreach ($value as $val) $table = $table . '<td>' . $val . '</td>';
                          $table = $table . '</tr>';
                      }
                      $table = $table . '<table>';
                      echo $table;
                      }break;
                  default : 
                      if($out) echo json_encode($out);  
              }
              

        })->via('GET', 'POST')->conditions(array('user_id' => '\d+', 'module' => '\w+', 'action' => '\w+'));
   
    });
    
    
    /*
     * @author   Tobi Martins
     * @since    1.0.0
     * Routes unhandled request appropriately
     */
    $app->notFound(function () {
           echo <<<EOT
                <center>Did you find what you are looking for - if not: visit <a href='#'>Moov API DOCS</a>
                <br> for Documentation.</center>
EOT;
        });
});
    
/*
 * @author   Tobi Martins
 * @since    1.0.0
 * Dispatch request with slims run method
 */
$app->run();
